package exam;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 程序界的山姆
 * @date 2020-09-04
 */
public class ThreadTest {
    private static Lock lock = new ReentrantLock();
    private static Condition condition1 = lock.newCondition();
    private static Condition condition2 = lock.newCondition();
    private static Condition condition3 = lock.newCondition();
    private static Condition condition4 = lock.newCondition();

    private static volatile int residueCount;
    private static volatile ArrayList<String> list;
    private static volatile int theadCount1;
    private static volatile int theadCount2;
    private static volatile int theadCount3;
    private static volatile int theadCount4;

    public void printABCD(int num) throws InterruptedException {
        list = new ArrayList<>(num);

        CountDownLatch allReady = new CountDownLatch(4);
        CountDownLatch allDone = new CountDownLatch(4);

        Thread thread1 = new Thread(()->{
            try {
                lock.lock();
                allReady.countDown();
                while (true) {
                    condition1.await();
                    if(list.size() >= num) {
                        condition2.signal();
                        break;
                    }
                    System.out.println("thread1获取了锁");
                    list.add("A");
                    condition2.signal();
                }
                allDone.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        });
        thread1.start();

        Thread thread2 = new Thread(()->{
            try {
                lock.lock();
                allReady.countDown();
                while (true) {
                    condition2.await();
                    if(list.size() >= num) {
                        condition3.signal();
                        break;
                    }
                    System.out.println("thread2获取了锁");
                    list.add("B");
                    condition3.signal();
                }
                allDone.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        });
        thread2.start();

        Thread thread3 = new Thread(()->{
            try {
                lock.lock();
                allReady.countDown();
                while (true) {
                    condition3.await();
                    if(list.size() >= num) {
                        condition4.signal();
                        break;
                    }
                    System.out.println("thread3获取了锁");
                    list.add("C");
                    condition4.signal();
                }
                allDone.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        });
        thread3.start();

        Thread thread4 = new Thread(()->{
            try {
                lock.lock();
                allReady.countDown();
                while (true) {
                    condition4.await();
                    if(list.size() >= num) {
                        condition1.signal();
                        break;
                    }
                    System.out.println("thread4获取了锁");
                    list.add("D");
                    condition1.signal();
                }
                allDone.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        });
        thread4.start();

        // 等待线程全部就绪
        allReady.await();

        lock.lock();
        try {
            // 触发线程1开始执行
            condition1.signal();
        } finally {
            lock.unlock();
        }

        // 等待线程全部完成
        allDone.await();

        System.out.println(list);
        System.out.println(list.size());
    }

    public static void main(String[] args) throws Exception {
        ThreadTest test = new ThreadTest();

        test.printABCD(18);
    }
}
